﻿namespace CookieTerm
{
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Xml.Serialization;

    public class DisplaySettingsCollection : KeyedCollection<string, DisplaySettings>
    {
        public DisplaySettingsCollection()
            : base(null, -1)
        {
        }

        protected override string GetKeyForItem(DisplaySettings item)
        {
            return item.Name;
        }
    }

    public class TerminalSettingsCollection : KeyedCollection<string, TerminalSettings>
    {
        protected override string GetKeyForItem(TerminalSettings item)
        {
            return item.Name;
        }
    }

    public class BookmarkCollection : KeyedCollection<string, Bookmark>
    {
        public BookmarkCollection()
            : base(null, -1)
        {
        }

        protected override string GetKeyForItem(Bookmark item)
        {
            return item.Name;
        }
    }

    public class BookmarkManager
    {
        private BookmarkCollection bookmarks = new BookmarkCollection();
        private DisplaySettingsCollection displaySettingsCollection = new DisplaySettingsCollection();
        private TerminalSettingsCollection terminalSettingsCollection = new TerminalSettingsCollection();

        public Collection<Bookmark> Bookmarks
        {
            get
            {
                return this.bookmarks;
            }
        }

        public Collection<DisplaySettings> DisplaySettingsCollection
        {
            get
            {
                return this.displaySettingsCollection;
            }
        }

        public Collection<TerminalSettings> TerminalSettingsCollection
        {
            get
            {
                return this.terminalSettingsCollection;
            }
        }

        public static BookmarkManager Deserialize(string s)
        {
            StringReader reader = new StringReader(s);
            return Deserialize(reader);
        }

        public static BookmarkManager Deserialize(TextReader reader)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(BookmarkManager));
            return (BookmarkManager)serializer.Deserialize(reader);
        }

        public DisplaySettings FindDisplaySettings(string name)
        {
            try
            {
                return this.displaySettingsCollection[name];
            }
            catch (KeyNotFoundException)
            {
                return DisplaySettings.Default;
            }
        }

        /// <summary>
        /// Create a display settings profile and add to the current collection.
        /// Use the default settings as a template.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public DisplaySettings CreateDisplaySettings(string name)
        {
            DisplaySettings newDisplaySettings = (DisplaySettings)DisplaySettings.Default.Clone();
            newDisplaySettings.Name = name;
            this.displaySettingsCollection.Add(newDisplaySettings);
            return newDisplaySettings;
        }

        public void RemoveDisplaySettings(DisplaySettings d)
        {
            this.displaySettingsCollection.Remove(d);

            foreach (Bookmark b in this.bookmarks)
            {
                DisplaySettings fallback = this.displaySettingsCollection.Count > 0 ? this.displaySettingsCollection[0] : DisplaySettings.Default;

                if (b.DisplaySettingsName == d.Name)
                {
                    b.DisplaySettings = fallback;
                }
            }
        }

        public TerminalSettings FindTerminalSettings(string name)
        {
            try
            {
                return this.terminalSettingsCollection[name];
            }
            catch (KeyNotFoundException)
            {
                return TerminalSettings.Default;
            }
        }

        public Bookmark FindBookmark(string name)
        {
            try
            {
                return this.bookmarks[name];
            }
            catch (KeyNotFoundException)
            {
                return null;
            }
        }

        public Bookmark CreateBookmark(string name, string hostname, int port, string displaySettingsName, string terminalSettingsName)
        {
            Bookmark bookmark = new Bookmark(this)
            {
                Name = name,
                Hostname = hostname,
                Port = port,
                DisplaySettingsName = displaySettingsName,
                TerminalSettingsName = terminalSettingsName,
                Manager = this
            };

            this.bookmarks.Add(bookmark);
            return bookmark;
        }

        public void RemoveBookmark(Bookmark b)
        {
            this.bookmarks.Remove(b);
        }

        public void Load()
        {
            try
            {
                StreamReader reader = new StreamReader(CookieTermAppSettings.BookmarkFile);
                BookmarkManager result = Deserialize(reader);

                reader.Close();

                this.bookmarks = result.bookmarks;
                this.displaySettingsCollection = result.displaySettingsCollection;
                this.terminalSettingsCollection = result.terminalSettingsCollection;

                this.FullyHydrate();
            }
            catch
            {
            }
        }

        public void Save()
        {
            StreamWriter writer = new StreamWriter(CookieTermAppSettings.BookmarkFile);
            this.Serialize(writer);
            writer.Close();
        }

        public string Serialize()
        {
            StringWriter writer = new StringWriter();
            this.Serialize(writer);
            return writer.ToString();
        }

        public void Serialize(TextWriter writer)
        {
            XmlSerializer serializer = new XmlSerializer(this.GetType());
            serializer.Serialize(writer, this);
        }

        private void FullyHydrate()
        {
            foreach (Bookmark b in this.bookmarks)
            {
                b.Manager = this;
            }
        }
    }
}
